
#include <string.h>

#include "misc.h"

static uint16_t str_table[8] = {
    0x0000, 0x0000, 0x4001, 0x03FF,
    0xFFFE, 0x07FF, 0xFFFE, 0x07FF
};
static uint32_t is_str_char_valid(uint8_t data) {
    if (data < 128) {
        return str_table[data >> 4] & (1 << (data & 0x0F));
    } else {
        return 0;
    }
}


int32_t data_to_num(uint8_t **p2data, uint32_t *plen, uint32_t *pnumber) {
    uint8_t *pdata = *p2data;
    uint32_t len = *plen;
    uint32_t number;
    //skip space
    while (len) {
        if (*pdata == ' ') {
            pdata++;
            len--;
        } else {
            break;
        }
    }
    if (!len) {
        return -1;
    } else if (!BETWEEN11('0', *pdata, '9')) {
        return -1;
    }
    for (number = 0; len > 0;) {
        if (BETWEEN11('0', *pdata, '9')) {
            number *= 10;
            number = number + *pdata - '0';
        } else {
            break;
        }
        pdata++;
        len--;
    }
    *p2data = pdata;
    *plen = len;
    *pnumber = number;
    return 0;
}
int32_t data_skip(uint8_t **p2data, uint32_t *plen, uint8_t data) {
    uint8_t *pdata = *p2data;
    uint32_t len = *plen;
    while (len) {
        if (*pdata == ' ') {
            pdata++;
            len--;
        } else {
            break;
        }
    }
    if (!len) {
        return -1;
    } else if (*pdata != data) {
        return -1;
    }
    pdata++;
    len--;
    *p2data = pdata;
    *plen = len;
    return 0;
}
//[0-9],[A-Z],[a-z],[space],[.]
static int32_t data_to_arg(uint8_t **p2data, uint32_t *plen, uint8_t **p2str, uint32_t *ps_len) {
    uint8_t *pdata = *p2data;
    uint32_t len = *plen;
    uint32_t pos;
    while (len) {
        if (*pdata == ' ') {
            pdata++;
            len--;
        } else {
            break;
        }
    }
    if (!len) {
        return -1;
    } else if (!is_str_char_valid(*pdata)) {
        return -1;
    }
    *p2str = pdata;
    for (pos = 0; len > 0;) {
        if (is_str_char_valid(*pdata)) {
            pos++;
        } else {
            break;
        }
        pdata++;
        len--;
    }
    *p2data = pdata;
    *plen = len;
    *ps_len = pos;
    return 0;
}

//ABCD or "ABCD"
int32_t data_to_str(uint8_t **p2data, uint32_t *plen, char **p2str, uint32_t *ps_len) {
    if (data_skip(p2data, plen, '"')) {
        return data_to_arg(p2data, plen, (uint8_t **)p2str, ps_len);
    } else {
        if (data_to_arg(p2data, plen, (uint8_t **)p2str, ps_len)) {
            return -1;
        }
        return data_skip(p2data, plen, '"');
    }
}
//string like "ABCD" in double qoutes
int32_t data_to_dqstr(uint8_t **p2data, uint32_t *plen, char **p2str, uint32_t *ps_len) {
    if (data_skip(p2data, plen, '"')) {
        return -1;
    }
    if (data_to_arg(p2data, plen, (uint8_t **)p2str, ps_len)) {
        return -1;
    }
    return data_skip(p2data, plen, '"');
}

int32_t str_all_number_pre(const char *pdata, uint32_t len) {
    uint32_t i;
    for (i = 0; i < len; i++) {
        if (!BETWEEN11('0', pdata[i], '9')) {
            return -1;
        }
    }
    return 0;
}

int32_t str_cmp(const char *pdata, uint32_t len, const char *pstr, uint32_t s_len) {
    if (len != s_len) {
        return -1;
    }
    while (len--) {
        if (*pdata != *pstr) {
            return -1;
        }
        pdata++;
        pstr++;
    }
    return 0;
}

static uint8_t hex_table[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };

int32_t bin_to_hstr(uint8_t *pdst, uint8_t *psrc, uint32_t len) {
    if ((pdst == NULL) || (psrc == NULL)) {
        return -1;
    }
    while (len--) {
        *pdst = hex_table[(*psrc & 0xF0) >> 4]; pdst++;
        *pdst = hex_table[*psrc & 0x0F]; pdst++;
        psrc++;
    }
    return 0;
}

int32_t hstr_to_bin(uint8_t *pdst, uint8_t *psrc, uint32_t len) {
    if ((pdst == NULL) || (psrc == NULL)) {
        return -1;
    }
    len <<= 1; /** len = len * 2 */
    while (len--) {
        if ((*psrc >= '0') && (*psrc <= '9')) {
            *pdst = (*psrc - '0') << 4;
        } else if ((*psrc >= 'a') && (*psrc <= 'f')) {
            *pdst = (*psrc - 87) << 4; //x-'a'+10
        } else if ((*psrc >= 'A') && (*psrc <= 'F')) {
            *pdst = (*psrc - 55) << 4; //x-'A'+10
        } else {
            return -1;
        }
        psrc++;
        if ((*psrc >= '0') && (*psrc <= '9')) {
            *pdst |= (*psrc - '0');
        } else if ((*psrc >= 'a') && (*psrc <= 'f')) {
            *pdst |= (*psrc - 87); //x-'a'+10
        } else if ((*psrc >= 'A') && (*psrc <= 'F')) {
            *pdst |= (*psrc - 55); //x-'A'+10
        } else {
            return -1;
        }
        psrc++;
        pdst++;
    }
    return 0;
}


static int32_t data_to_u32_intern(uint8_t **p2data, uint32_t *plen, uint32_t *pnumber) {
    uint8_t *pdata = *p2data;
    uint32_t len = *plen;
    uint32_t number;
    for (number = 0; len > 0; len--, pdata++) {
        if (BETWEEN11('0', *pdata, '9')) {
            if (number > 429496729U) { //number > (UINT32_MAX / 10)
                return -1;
            } else {
                number *= 10;
                if ((UINT32_MAX - number) < (*pdata - '0')) {
                    return -1;
                }
                number += (*pdata - '0');
            }
        } else {
            if (len == *plen) { //first character is not a number
                return -1;
            } else {
                break;
            }
        }
    }
    *p2data = pdata;
    *plen = len;
    *pnumber = number;
    return 0;
}


int32_t data_to_u32(uint8_t **p2data, uint32_t *plen, uint32_t *pnumber) {
    uint8_t *pdata = *p2data;
    uint32_t len = *plen;
    uint32_t number;
    //skip space
    for (; len > 0; len--, pdata++) {
        if (*pdata != ' ') {
            break;
        } else if (len == 1) { //last space
            return -1;
        }
    }
    if (*pdata == '+') {
        if (len == 1) {
            return -1;
        } else {
            pdata++;
            len--;
        }
    }
    if (data_to_u32_intern(&pdata, &len, &number)) {
        return -1;
    }
    *p2data = pdata;
    *plen = len;
    *pnumber = number;
    return 0;
}

int32_t data_to_s32(uint8_t **p2data, uint32_t *plen, int32_t *pnumber) {
    uint8_t *pdata = *p2data;
    uint32_t len = *plen;
    int32_t number;
    //skip space
    for (; len > 0; len--, pdata++) {
        if (*pdata != ' ') {
            break;
        } else if (len == 1) { //last space
            return -1;
        }
    }
    if (*pdata == '-') { //positive | zero
        if (len == 1) {
            return -1;
        } else {
            pdata++;
            len--;
        }
        if (data_to_u32_intern(&pdata, &len, (uint32_t *)&number)) {
            return -1;
        }

        if ((number < 0) && (number != INT32_MIN)) { //-2147483648 and 2147483648 are the same presentation
            return -1;
        }
        number = 0 - number;
    } else if (*pdata == '+') { //negative | zero
        if (len == 1) {
            return -1;
        } else {
            pdata++;
            len--;
        }
        if (data_to_u32_intern(&pdata, &len, (uint32_t *)&number)) {
            return -1;
        }
        if (number < 0) {
            return -1;
        }
    } else { //positive | zero
        if (data_to_u32_intern(&pdata, &len, (uint32_t *)&number)) {
            return -1;
        }
        if (number < 0) {
            return -1;
        }
    }
    *p2data = pdata;
    *plen = len;
    *pnumber = number;
    return 0;
}


#include "SEGGER_RTT.h"
#include "drv_net.h"

void show_data(uint8_t *pdata, uint32_t len, uint32_t flag_hex) {
    uint32_t i;
    if (flag_hex) {
        for (i = 0; i < len; i++) {
            NET_PUTCHAR(hex_table[pdata[i] >> 4]);
            NET_PUTCHAR(hex_table[pdata[i] & 0x0F]);
        }
    } else {
        for (i = 0; i < len; i++) {
            NET_PUTCHAR(pdata[i]);
        }
    }
}

void show_one_data(uint8_t data) {
    NET_PUTCHAR(hex_table[data >> 4]);
    NET_PUTCHAR(hex_table[data & 0x0F]);
}


